第六章 朴素贝叶斯模型¶

6.1 朴素贝叶斯模型的算法原理¶

  • 贝叶斯分类是机器学习中应用极为广泛的分类算法之一, 产生自英国数学家贝叶斯对于逆概问题的思考

  • 朴素贝叶斯是贝叶斯模型当中最简单的一种, 其算法核心为$$P(A|B) = \frac{P(B|A)P(A)}{P(B)}$$

6.1.2 二维变量下的贝叶斯模型¶

  • 计算公式$$P(Y|X_1,X_2) = \frac{P(X_1,X_2|Y)P(Y)}{P(X_1,X_2)}$$

  • 独立性假设$$P(X_1, X_2|Y) = P(X_1|Y)P(X_2|Y)$$

6.1.4 朴素贝叶斯模型的简单代码实现¶

In [1]:
import warnings

warnings.filterwarnings('ignore')
In [2]:
from sklearn.naive_bayes import GaussianNB#引入朴素贝叶斯模型(这里用的是高斯贝叶斯分类器)
X = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
y = [0, 0, 0, 1, 1]

model = GaussianNB()
model.fit(X, y)

print(model.predict([[5, 5]]))
[0]

训练过程

  1. 计算先验概率 $P(C)$: 在给定的标签 y = [0, 0, 0, 1, 1] 中,总共有 $n = 5$ 个样本。其中类别 $C = 0$ 出现了 $n_0 = 3$ 次,类别 $C = 1$ 出现了 $n_1 = 2$ 次。 根据先验概率的计算方法,$P(C = 0)=\frac{n_0}{n}=\frac{3}{5}= 0.6$ ,$P(C = 1)=\frac{n_1}{n}=\frac{2}{5}= 0.4$ 。

  2. 计算条件概率 $P(X|C)$: 由于这里使用的是高斯朴素贝叶斯,假设每个特征在不同类别下服从高斯分布(正态分布)。对于每个类别 $C$ 和每个特征维度 $j$ ,需要计算该维度特征的均值 $\mu_{C,j}$ 和方差 $\sigma_{C,j}^2$ 。

    • 以特征维度 $j = 0$ (即每个样本的第一个值)为例:
      • 当 $C = 0$ 时,对应的特征值为 [1, 3, 5] ,其均值 $\mu_{0,0}=\frac{1 + 3+ 5}{3}= 3$ ,方差 $\sigma_{0,0}^2=\frac{(1 - 3)^2+(3 - 3)^2+(5 - 3)^2}{3}=\frac{8}{3}\approx 2.67$ 。
      • 当 $C = 1$ 时,对应的特征值为 [7, 9] ,其均值 $\mu_{1,0}=\frac{7 + 9}{2}= 8$ ,方差 $\sigma_{1,0}^2=\frac{(7 - 8)^2+(9 - 8)^2}{2}= 1$ 。
    • 同理可计算特征维度 $j = 1$ (即每个样本的第二个值)在不同类别下的均值和方差。

得到均值和方差后,对于新样本的某个特征值 $x_j$ ,可以根据高斯分布的概率密度函数 $P(x_j|\mu_{C,j},\sigma_{C,j}^2)=\frac{1}{\sqrt{2\pi\sigma_{C,j}^2}}e^{-\frac{(x_j - \mu_{C,j})^2}{2\sigma_{C,j}^2}}$ 计算条件概率 $P(x_j|C)$ 。在多特征情况下,基于特征条件独立假设,$P(X|C)=\prod_{j}P(x_j|C)$ 。

贝叶斯公式的运用

在预测新样本 [5, 5] 时,根据贝叶斯公式 $P(C|X)=\frac{P(X|C)P(C)}{P(X)}$ ,计算该样本属于每个类别的后验概率 $P(C|X)$ :

  • 因为 $P(X)$ 对于所有类别都是相同的,在比较不同类别后验概率大小时可以不考虑。所以只需计算 $P(X|C)P(C)$ 。
  • 对于类别 $C = 0$ ,先计算 $P(X|C = 0)$ ,即 $P(5|\mu_{0,0},\sigma_{0,0}^2)\times P(5|\mu_{0,1},\sigma_{0,1}^2)$ (假设已计算出特征维度 $j = 1$ 在 $C = 0$ 时的均值和方差 ),再乘以 $P(C = 0)=0.6$ ,得到 $P(X|C = 0)P(C = 0)$ 。
  • 对于类别 $C = 1$ ,同样计算 $P(X|C = 1)$ ,即 $P(5|\mu_{1,0},\sigma_{1,0}^2)\times P(5|\mu_{1,1},\sigma_{1,1}^2)$ (假设已计算出特征维度 $j = 1$ 在 $C = 1$ 时的均值和方差 ),再乘以 $P(C = 1)=0.4$ ,得到 $P(X|C = 1)P(C = 1)$ 。

最后比较 $P(X|C = 0)P(C = 0)$ 和 $P(X|C = 1)P(C = 1)$ 的大小,将新样本归为后验概率较大的类别。

6.2 案例实战: 肿瘤预测模型¶

6.2.2 数据读取与划分¶

6.2.2.1 读取数据¶

In [3]:
#读取数据

import pandas as pd
df = pd.read_excel('肿瘤数据.xlsx')
print(df.head())

print(df.columns)

'''
columns:

  最大周长: 所有肿瘤中周长最大的三个值的平均值

  最大凹陷度: 所有肿瘤中凹陷度最大的三个值的平均值

  最大面积: 所有肿瘤中面积最大的三个值的平均值

  最大半径: 所有肿瘤中半径最大的三个值的平均值

  平均灰度值: 所有肿瘤图像灰度值的平均值

  肿瘤性质: 0代表恶性, 1代表良性


'''
     最大周长   最大凹陷度    平均凹陷度    最大面积   最大半径  平均灰度值  肿瘤性质
0  184.60  0.2654  0.14710  2019.0  25.38  17.33     0
1  158.80  0.1860  0.07017  1956.0  24.99  23.41     0
2  152.50  0.2430  0.12790  1709.0  23.57  25.53     1
3   98.87  0.2575  0.10520   567.7  14.91  26.50     0
4  152.20  0.1625  0.10430  1575.0  22.54  16.67     0
Index(['最大周长', '最大凹陷度', '平均凹陷度', '最大面积', '最大半径', '平均灰度值', '肿瘤性质'], dtype='object')
Out[3]:
'\ncolumns:\n\n  最大周长: 所有肿瘤中周长最大的三个值的平均值\n\n  最大凹陷度: 所有肿瘤中凹陷度最大的三个值的平均值\n\n  最大面积: 所有肿瘤中面积最大的三个值的平均值\n\n  最大半径: 所有肿瘤中半径最大的三个值的平均值\n\n  平均灰度值: 所有肿瘤图像灰度值的平均值\n\n  肿瘤性质: 0代表恶性, 1代表良性\n\n\n'

6.2.2.2 划分特征变量和目标变量¶

In [4]:
# 划分特征变量和目标变量

X = df.drop(columns='肿瘤性质') 
y = df['肿瘤性质']   

6.2.3 模型的搭建与使用¶

6.2.3.1 划分训练集和测试集¶

In [5]:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)

6.2.3.2 模型搭建¶

In [6]:
from sklearn.naive_bayes import GaussianNB
nb_clf = GaussianNB()  # 高斯朴素贝叶斯模型
nb_clf.fit(X_train,y_train)
Out[6]:
GaussianNB()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GaussianNB()

6.2.3.3 模型预测与评估¶

In [7]:
y_pred = nb_clf.predict(X_test)

print(y_pred)
[1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 1 1 1 1 0 1 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 0
 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0
 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0
 1 1 1]
In [8]:
a = pd.DataFrame()

a['预测值'] = list(y_pred)
a['实际值'] = list(y_test)

print(a.head(10))
   预测值  实际值
0    1    1
1    0    0
2    1    1
3    0    0
4    1    0
5    0    0
6    0    0
7    0    0
8    1    1
9    1    1
In [9]:
from sklearn.metrics import accuracy_score
score = accuracy_score(y_pred = y_pred, y_true=y_test)

print(score)
0.9473684210526315